package org.jc.reflect.service;

import java.lang.reflect.InvocationTargetException;

import org.jc.reflect.model.JField;
import org.jc.reflect.model.JMethod;
import org.jc.reflect.utils.JReflectUtil;

public abstract class JReflectProxy<T> implements JReflectService {

	private T instance = null;

	private JMethod[] methods = null;
	private JField[] fields = null;

	private boolean load_static = true;
	private boolean load_private = true;;

	@SuppressWarnings("unused")
	private JReflectProxy() {
	}

	public JReflectProxy(T instance) {
		this.instance = instance;
		this.init();
	}

	public JReflectProxy(T instance, boolean load_static, boolean load_private) {
		this.instance = instance;
		this.load_static = load_static;
		this.load_private = load_private;
		this.init();
	}

	private void init() {
		this.methods = JReflectUtil.getMethods(instance.getClass(), this.load_static, this.load_private)
				.toArray(new JMethod[] {});
		this.fields = JReflectUtil.getFields(instance.getClass(), this.load_static).toArray(new JField[] {});
	}

	@Override
	public JMethod[] getMethods() {
		return this.methods;
	}

	@Override
	public Object invokeMethod(int i, Object[] params) throws IllegalAccessException, IllegalArgumentException,
			InvocationTargetException, NoSuchMethodException, SecurityException {
		JMethod jMethod = methods[i];
		Object value = this.invokeMethod(jMethod, params);
		return value;
	}

	@Override
	public Object invokeMethod(JMethod jMethod, Object[] params) throws IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		Object value = this.invokeMethod(jMethod.getName(), jMethod.getParamTypes(), params);
		return value;
	}

	@Override
	public Object invokeMethod(String methodName, Class<?>[] paramTypes, Object[] params) throws IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		Object value = JReflectUtil.invoke(instance, methodName, paramTypes, params);
		return value;
	}

	@Override
	public JField[] getFields() {
		return this.fields;
	}


	@Override
	public Object invokeGetField(String fieldName)
			throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
		Object value = JReflectUtil.invokeGetField(instance, fieldName, true);
		return value;
	}

	@Override
	public Object invokeGetField(String fieldName, boolean accessible)
			throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
		Object value = JReflectUtil.invokeGetField(instance, fieldName, accessible);
		return value;
	}

	@SuppressWarnings("hiding")
	@Override
	public <T> void invokeSetField(T instance, String fieldName, Object value)
			throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		JReflectUtil.invokeSetField(instance, fieldName, value, true);
	}

	@SuppressWarnings("hiding")
	@Override
	public <T> void invokeSetField(T instance, String fieldName, Object value, boolean accessible)
			throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		JReflectUtil.invokeSetField(instance, fieldName, value, accessible);
	}

}
